#******************************************************************************
#******************************************************************************

# import libraries

import random

import numpy as np

import fluids

from src.hyhetra.pipes.classes import StandardisedPipe, StandardisedPipeDatabase

import src.hyhetra.pipes.fic as fic

from numpy.testing import assert_allclose

# from math import isclose

#******************************************************************************
#******************************************************************************

def examples(singlepipedb: StandardisedPipeDatabase):

    # # load pipe data
        
    # pipedata_files = ['data/pipes/singlepipes_s1.csv',
    #                   'data/pipes/singlepipes_s2.csv',
    #                   'data/pipes/singlepipes_s3.csv']
    
    # singlepipedb = StandardisedPipeDatabase(source=pipedata_files)
    
    # tests
    
    example_darcy_friction_factor(singlepipedb)
    
    example_dff_initial_solution_smooth_pipes(singlepipedb)
    
    example_dff_initial_solution_rough_pipes(singlepipedb)

#******************************************************************************
#******************************************************************************

def example_darcy_friction_factor(pipedb):
    
    # test specific friction factor models against validated ones
    
    # number of points
    
    number_points_laminar = 10
    
    number_points_turbulent = 100
    
    # define the reynolds numbers' vector

    # list_reynolds_number = np.concatenate(
    #     (np.linspace(fic.LAMINAR_LOWER_RE_LIMIT,
    #                  fic.LAMINAR_UPPER_RE_LIMIT, 
    #                  number_points_laminar), 
    #      np.linspace(fic.TURBULENT_LOWER_RE_LIMIT, 
    #                  fic.TURBULENT_UPPER_RE_LIMIT, 
    #                  number_points_turbulent)), 
    #     axis=0)

    list_reynolds_number = np.linspace(
        fic.TURBULENT_LOWER_RE_LIMIT, 
        fic.TURBULENT_UPPER_RE_LIMIT, 
        number_points_turbulent)
    
    # specify the pipes
    
    number_pipe_tuples = 5
    
    # get number_pipe_tuples random pipe tuples from the database
    
    list_pipe_tuples = [pipe_tuple 
                        for i, pipe_tuple in enumerate(pipedb.pipe_tuples)
                        if random.randint(0,1)][0:number_pipe_tuples]

    list_relative_pipe_roughness = [
        0,
        1e-5,
        1e-4,
        1e-3,
        1e-2]
    
    list_pipes = [
        StandardisedPipe(
            pipe_tuple=pipe_tuple,
            e_rel=relative_pipe_roughness,
            db=pipedb)
        for pipe_tuple in list_pipe_tuples
        for relative_pipe_roughness in list_relative_pipe_roughness]
    
    # friction factor relative tolerance
    
    dff_relative_tolerance = 0.05
    
    #**************************************************************************
    #**************************************************************************
    
    # for each pipe
    
    for pipe in list_pipes:
        
        # for each reynolds number
        
        for reynolds_number in list_reynolds_number:
        
            # calculate the friction factor
            
            dff = fic.DarcyFrictionFactor(reynolds_number,
                                          pipe)
            
            # calculate the friction factor using 'fluids'
            
            dff_true = fluids.friction_factor(reynolds_number,
                                              pipe.e_rel)
            
            # check
            
            assert_allclose(dff,
                            dff_true,
                            rtol=dff_relative_tolerance)
        
    #**************************************************************************
    #**************************************************************************

#******************************************************************************
#******************************************************************************

def example_dff_initial_solution_smooth_pipes(pipedb):
    
    # test specific friction factor models against validated ones
    
    model = fic.DFF_PETHUKOV
    
    # number of points
    
    number_points_turbulent = 100
    
    # define the reynolds numbers' vector

    list_reynolds_number = np.linspace(
        fic.DFF_RE_LIMITS[model][0], 
        fic.DFF_RE_LIMITS[model][1],
        number_points_turbulent)
    
    # specify the pipes

    # list_pipe_tuples = [(20,1),
    #                     (25,1),
    #                     (32,1),
    #                     (40,1),
    #                     (50,1),
    #                     (65,1),
    #                     (80,1),
    #                     (100,1),
    #                     (125,1),
    #                     (150,1),
    #                     (200,1)]
                        
    number_pipe_tuples = 5
    
    # get number_pipe_tuples random pipe tuples from the database
    
    list_pipe_tuples = [pipe_tuple 
                        for i, pipe_tuple in enumerate(pipedb.pipe_tuples)
                        if random.randint(0,1)][0:number_pipe_tuples]

    list_relative_pipe_roughness = [ 0] # smooth pipes only
    
    list_pipes = [
        StandardisedPipe(
            pipe_tuple=pipe_tuple,
            e_rel=relative_pipe_roughness,
            db=pipedb)
        for pipe_tuple in list_pipe_tuples
        for relative_pipe_roughness in list_relative_pipe_roughness]
    
    # friction factor relative tolerance
    
    dff_relative_tolerance = 0.05
    
    #**************************************************************************
    #**************************************************************************
        
    # for each pipe
    
    for pipe in list_pipes:
    
        # for each reynolds number
        
        for reynolds_number in list_reynolds_number:
            
            _, dff = fic.DarcyFrictionFactorExplicit(
                pipe,
                model=model,
                reynolds_number=reynolds_number)
            
            # calculate the friction factor using 'fluids'
            
            dff_true = fluids.friction_factor(reynolds_number,
                                              pipe.e_rel)
            
            # check
            
            assert_allclose(dff,
                            dff_true,
                            rtol=dff_relative_tolerance)
            
        
    #**************************************************************************
    #**************************************************************************

#******************************************************************************
#******************************************************************************

def example_dff_initial_solution_rough_pipes(pipedb):
    
    # test specific friction factor models against validated ones
    
    model = fic.DFF_NIKURADSE
    
    # # load pipe data
        
    # pipedata_files = ['data/pipes/singlepipes_s1.csv',
    #                   'data/pipes/singlepipes_s2.csv',
    #                   'data/pipes/singlepipes_s3.csv']
    
    # pipedb = StandardisedPipeDatabase(source=pipedata_files)
    
    # # number of points
    
    # number_points_laminar = 10
    
    # number_points_turbulent = 100
    
    # # define the reynolds numbers' vector

    # # list_reynolds_number = np.concatenate(
    # #     (np.linspace(fic.LAMINAR_LOWER_RE_LIMIT,
    # #                  fic.LAMINAR_UPPER_RE_LIMIT, 
    # #                  number_points_laminar), 
    # #      np.linspace(fic.TURBULENT_LOWER_RE_LIMIT, 
    # #                  fic.TURBULENT_UPPER_RE_LIMIT, 
    # #                  number_points_turbulent)), 
    # #     axis=0)

    # list_reynolds_number = np.linspace(
    #     fic.TURBULENT_LOWER_RE_LIMIT, 
    #     fic.TURBULENT_UPPER_RE_LIMIT, 
    #     number_points_turbulent)
    
    list_reynolds_number = [fic.DFF_RE_LIMITS[model][1]]
    
    # define the pipes

    # list_pipe_tuples = [(20,1),
    #                     (25,1),
    #                     (32,1),
    #                     (40,1),
    #                     (50,1),
    #                     (65,1),
    #                     (80,1),
    #                     (100,1),
    #                     (125,1),
    #                     (150,1),
    #                     (200,1)]
    
    number_pipe_tuples = 5
    
    # get number_pipe_tuples random pipe tuples from the database
    
    list_pipe_tuples = [pipe_tuple 
                        for i, pipe_tuple in enumerate(pipedb.pipe_tuples)
                        if random.randint(0,1)][0:number_pipe_tuples]

    list_relative_pipe_roughness = [
        #0,
        #1e-5,
        #5e-4,
        1e-3,
        1e-2,
        5e-2]
    
    list_pipes = [
        StandardisedPipe(
            pipe_tuple=pipe_tuple,
            e_rel=relative_pipe_roughness,
            db=pipedb)
        for pipe_tuple in list_pipe_tuples
        for relative_pipe_roughness in list_relative_pipe_roughness]
    
    # friction factor relative tolerance
    
    dff_relative_tolerance = 0.05
    
    #**************************************************************************
    #**************************************************************************
        
    # for each pipe
    
    for pipe in list_pipes:
    
        # for each reynolds number
        
        for reynolds_number in list_reynolds_number:
                
            _, dff = fic.DarcyFrictionFactorExplicit(
                pipe,
                model=model,
                reynolds_number=None)
            
            # calculate the friction factor using 'fluids'
            
            dff_true = fluids.friction_factor(reynolds_number,
                                              pipe.e_rel)
            
            # check
            
            assert_allclose(dff,
                            dff_true,
                            rtol=dff_relative_tolerance)
        
    #**************************************************************************
    #**************************************************************************

#******************************************************************************
#******************************************************************************